# 该函数用于消除量纲的影响
# 参考P327页数据变换(聚类分析与判别分析)
# 参考P392页定量指标值的无量纲处理(综合评价方法)

import numpy as np
import pandas as pd

# 注意：
# 1、矩阵参数返回三个值
        # ResultList，所有列的结果
        # UsefulList，所有列去除掉nan的结果
        # Data_Frame,去除掉nan的矩阵结果
# 2、如果参数是列表list或者array,则只会按照单行处理而不会按照矩阵来处理

# 3、ResultList, UsefulList, Data_Frame

# 需要注意是否有其他不相关数据进入了算法,例如年份、编号等数据，否则也会带入计算造成结果不正确


# 1、中心化处理
# 默认按列来中心化
def Center_Translate(Data, axis=1):
    print('=============================数据中心化处理=============================')
    # 数据为DataFrame矩阵型
    if type(Data) == pd.DataFrame:
        # 数据为DataFrame的矩阵格式
        ResultList = []
        TrueColumns = []
        for i in range(Data.shape[1]):
            LResult = []
            if Data.iloc[:, i].dtype == 'object':
                #print('列索引:', i, ',', Data.columns[i].replace("\n", ""), ',其类型为', Data.iloc[:, i].dtype, ',不可取得均值')
                # 无法进行中心化处理的,其位置填充为NaN
                LResult = np.nan
            elif Data.iloc[:, i].dtype == 'float64' or Data.iloc[:, i].dtype == 'int64':
                # print(Data.columns[i].replace("\n", ""), '其类型为', Data.iloc[:, i].dtype)
                # 获取该列数据
                L = np.array(Data.iloc[:, i])
                # 计算列平均值
                Lmean = L.mean()
                for value in L:
                    # 减去其平均值
                    value = value - Lmean
                    LResult.append(value)
                TrueColumns.append(Data.columns[i])

            # 将该列的结果加入总结果里面
            ResultList.append(LResult)

        # 将中心化之后的数据变成矩阵形状
        # 有用的列的列表
        UsefulList = []
        for i in ResultList:
            if type(i) != type(np.nan):
                # print('i:',type(i))
                # print('i:',i)
                UsefulList.append(i)
        # print('useful:\n',UsefulList)
        # 将列的形状转换到适合的形状
        UsefulList = np.array(UsefulList).T
        UsefulList = UsefulList.flatten().reshape(Data.shape[0], len(TrueColumns))
        # print('resultlist:\n',ResultList)
        # 初始化新的矩阵
        Data_Frame = pd.DataFrame(UsefulList, index=Data.index, columns=TrueColumns)

        # ResultList，所有列的结果
        # UsefulList，所有列去除掉nan的结果
        # Data_Frame,去除掉nan的矩阵结果
        return ResultList, UsefulList, Data_Frame
    # 为nadarry型
    elif type(Data) == np.ndarray:
        DataMean = Data.mean()
        for value in Data:
            value = value - DataMean
        return Data
    # 为list列表型
    elif type(Data) == list:
        Data = np.array(Data)
        DataMean = Data.mean()
        for value in Data:
            value = value - DataMean
        return Data


# 2、规格化处理
def Normalized_Translate(Data):
    print('=============================数据规格化变换=============================')
    # 数据为DataFrame矩阵型
    if type(Data) == pd.DataFrame:
        # 数据为DataFrame的矩阵格式
        ResultList = []
        TrueColumns = []
        for i in range(Data.shape[1]):
            LResult = []
            if Data.iloc[:, i].dtype == 'object':
                # print('列索引:', i, ',', Data.columns[i].replace("\n", ""), ',其类型为', Data.iloc[:, i].dtype, ',不可取得均值')
                # 无法进行中心化处理的,其位置填充为NaN
                LResult = np.nan
            elif Data.iloc[:, i].dtype == 'float64' or Data.iloc[:, i].dtype == 'int64':
                # print(Data.columns[i].replace("\n", ""), '其类型为', Data.iloc[:, i].dtype)
                # 获取该列数据
                L = np.array(Data.iloc[:, i])
                # 计算极差
                Delta = L.max() - L.min()
                # 计算最小值
                Minvalue = L.min()
                for value in L:
                    # 减去其平均值
                    value = (value - Minvalue) / Delta
                    LResult.append(value)
                TrueColumns.append(Data.columns[i])

            # 将该列的结果加入总结果里面
            ResultList.append(LResult)

        # 将中心化之后的数据变成矩阵形状
        # 有用的列的列表
        UsefulList = []
        for i in ResultList:
            if i==i:
                # print('i:',type(i))
                # print('i:',i)
                UsefulList.append(i)
        # print('useful:\n',UsefulList)
        # 将列的形状转换到适合的形状
        UsefulList = np.array(UsefulList).T
        UsefulList = UsefulList.flatten().reshape(Data.shape[0], len(TrueColumns))
        # print('resultlist:\n',ResultList)
        # 初始化新的矩阵
        Data_Frame = pd.DataFrame(UsefulList, index=Data.index, columns=TrueColumns)

        # ResultList，所有列的结果
        # UsefulList，所有列去除掉nan的结果
        # Data_Frame,去除掉nan的矩阵结果
        return ResultList, UsefulList, Data_Frame
    # 为nadarry型
    elif type(Data) == np.ndarray:
        # 计算极差
        Delta = Data.max() - Data.min()
        # 计算最小值
        Minvalue = Data.min()
        for value in Data:
            value = (value - Minvalue) / Delta
        return Data
    # 为list列表型
    elif type(Data) == list:
        Data = np.array(Data)
        # 计算极差
        Delta = Data.max() - Data.min()
        # 计算最小值
        Minvalue = Data.min()
        for value in Data:
            value = (value - Minvalue) / Delta
        return Data


# 3、标准化
# 对于要求指标值大于0的评价方法,如熵值法和几何加权平均法等该数据处理方法不适用
def Standard_Translate(Data):
    # 数据为DataFrame矩阵型
    # 返回三个值
    if type(Data) == pd.DataFrame:
        # 数据为DataFrame的矩阵格式
        ResultList = []
        TrueColumns = []
        for i in range(Data.shape[1]):
            LResult = []
            if Data.iloc[:, i].dtype == 'object':
                # print('列索引:', i, ',', Data.columns[i].replace("\n", ""), ',其类型为', Data.iloc[:, i].dtype, ',不可取得均值')
                # 无法进行中心化处理的,其位置填充为NaN
                LResult = np.nan
            elif Data.iloc[:, i].dtype == 'float64' or Data.iloc[:, i].dtype == 'int64':
                # print(Data.columns[i].replace("\n", ""), '其类型为', Data.iloc[:, i].dtype)
                # 获取该列数据
                L = np.array(Data.iloc[:, i])
                # 计算列平均值
                Lmean = L.mean()
                # 计算标准差
                S=np.std(L,ddof=1)
                # print('Lmean:\n',Lmean)
                # print('S:\n',S)
                for value in L:
                    # 减去其平均值再除以标准差
                    value = (value - Lmean)/S
                    # print('Value:',value)
                    LResult.append(value)
                TrueColumns.append(Data.columns[i])
            # print('LResult:\n',LResult)
            # 将该列的结果加入总结果里面
            ResultList.append(LResult)

        # 将中心化之后的数据变成矩阵形状
        # 有用的列的列表
        UsefulList = []
        for i in ResultList:
            if i == i:
                # print('i:',type(i))
                # print('i:',i)
                UsefulList.append(i)
        # print('useful:\n',UsefulList)
        # 将列的形状转换到适合的形状
        UsefulList = np.array(UsefulList).T
        UsefulList = UsefulList.flatten().reshape(Data.shape[0], len(TrueColumns))
        # print('resultlist:\n',ResultList)
        # 初始化新的矩阵
        Data_Frame = pd.DataFrame(UsefulList, index=Data.index, columns=TrueColumns)

        # ResultList，所有列的结果
        # UsefulList，所有列去除掉nan的结果
        # Data_Frame,去除掉nan的矩阵结果
        return ResultList, UsefulList, Data_Frame
    # 为nadarry型
    elif type(Data) == np.ndarray:
        DataMean = Data.mean()
        S=Data.std()
        for value in Data:
            value = (value - DataMean)/S
        return Data
    # 为list列表型
    elif type(Data) == list:
        Data = np.array(Data)
        DataMean = Data.mean()
        S=Data.std()
        for value in Data:
            value = (value - DataMean)/S
        return Data

# 4、比例变换法
# 该方法的优点是这些变换前后的属性值成比例
# 默认都为极大型指标
def Scale_Translate(Data):
    Data=Data/np.max(Data)
    return Data

# 5、向量归一化法
def Normalization_translate(Data):
    Data=Data/((sum(Data**2))**0.5)
    return Data

# 6、极差变换法
# 其特点是变换后所有数据都在[0,1]区间上,且都有最优值1和最劣值0
# 缺点是是变换前后各指标值不成比例
def Range_Translate(Data):
    Data=(Data-min(Data))/(max(Data)-min(Data))
    return Data




